home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
tool
/
athena
/
athena.c
next >
Wrap
Text File
|
1995-02-18
|
26KB
|
1,035 lines
/*
8086|Printman/TEXT 'Athena' Version 1.00a
With 8086|Printman Library Version 1.20
Copyright (c) 1995 Delmonta
コンパイル時の注意:
(1)8086|Printman Library Ver1.20以上を必ずリンクすること
(2)クォートで括った文字列を分解せずにmainに渡す
スタートアップルーチンを必ずリンクすること
参考:
(1)浮動小数点演算は使っていない。printfなどは小数に対応していない
サブセット版をリンクしてもよい。
*/
/*------------------------ヘッダのインクルード-------------------------------*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<jctype.h>
#include<jstring.h>
#include<DEL_PRN.H>
/*---------------------------------マクロ関数--------------------------------*/
#ifdef DEBUG
#define DEBUGPRINT(f) printf f
#else
#define DEBUGPRINT(f)
#endif
#define BYTEWIDTH(c) (1+((c)>=256)) /* cが全角なら2、半角なら1 */
#define CEIL(a,b) (((a)+(b)-1)/(b)) /* aをbで割り端数を切り上げ */
#ifndef DOT2MM
#define DOT2MM(n) ((n)*127L/900) /* ドット数からmmへの換算 */
#endif
/*----------------------------------型と定数---------------------------------*/
typedef unsigned short ushort;
#define LINE_MAXCHARNUM 256 /* 1行の最大の文字数 */
#define HEADER_YSPACE 36 /* ヘッダの後にあけるドット数 */
#define FOOTER_YSPACE 36 /* フッタの後にあけるドット数 */
static const int Papersize[2][8] =
{
{1189, 841,594,420,297,210,148,105}, /* A0~A6 */
{1456,1030,728,515,364,257,182,128}, /* B0~B6 */
};
static const char Lastillegal_tbl[] =
"‘“(〔[{〈《「『【<`([{「<";
static const char Firstillegal_tbl[] =
"゛゜、。,.・:;?!’”)〕]}〉》」』】>゙゚、。,.・;:?!')]}」>/"
"ぁぃぅぇぉゃゅょっァィゥェォャュョッゎヮヵヶァィゥェォャュョッ";
/*--------------------------------変数---------------------------------------*/
static char *Pathname; /* 現在出力中のファイルのフルパス*/
static char *Filename; /* 同 パス名を除く部分 */
static int Pagenum; /* ページ番号 */
static int Linenum; /* 現在Linebufにたまっている行数 */
extern enum PRNBIOS Prn_machine = PRNBIOS_TOWNS; /* (-C) */
extern enum PRNMODE Prn_mode = PRNMODE_ESCP; /* (-P) */
static struct /* コマンドラインから受け取ったオプション ; 単位は基本的にmm */
{
struct {int x,y;} papersize; /* 用紙サイズ (-S) */
struct {int u,l;} pmargin; /* 物理マージン(-L) */
struct {int u,l,r,d;} lmargin; /* 論理マージン(-M) */
char *header; /* ヘッダ (-H) */
char *footer; /* フッタ (-F) */
struct {int num,space;}block; /* 段組 (-K) */
struct {int x,y;} charnum; /* 段の字数 (-N) */
struct {int s,e;int n;}area; /* 出力する範囲(-A) */
int tabstop; /* タブ幅 (-T) */
int istategaki; /* 縦書きの指定(-W) */
int tostdout; /* 標準出力へ (-P!) */
} Options = {{182,257},{9,3},{20,10,10,20},NULL,NULL,{1,10},{80,40},{1,9999,0},
8,0, 0};
static struct /* 変換した書式パラメータ ; 単位は全てドット=1/180インチ */
{
struct {int x,y;} blocksize; /* 段の大きさ */
int xwidth; /* 印刷可能領域の横幅 */
struct {int u,l;} margin; /* 物理マージンを差引いたマージン */
int blockspace; /* 段間スペース */
} Format;
static struct LINEBUF
{
int charnum;
int bytenum;
ushort *buf;
} *Linebuf;
/*****************************************************************************/
/* 8086|Printman Libraryに直接関係する部分 */
/*****************************************************************************/
/*-------------------------------エラー処理----------------------------------*/
extern enum PRNHERR prn_harderr(void)
{
char c;
fputs("\nプリンタエラーです.\n中止<A>, 再試行<R>, 無視<I>?",stderr);
rep:
c = getch();
switch(c)
{
case 'A':
case 'a':
fputs("A\n",stderr);
exit(1);
case 'R':
case 'r':
fputs("R\n",stderr);
return PRNHERR_RETRY;
case 'I':
case 'i':
fputs("I\n",stderr);
return PRNHERR_IGNORE;
default:
putc('\a',stderr);
goto rep;
}
}
/*--------------------------------改行処理-----------------------------------*/
/* prn_linefeed()+MSXプリンタでは一度に99/180インチまでしか改行できない */
/* (ESC/Pは255/180、PC-PRでは99/120)ので、それより大きい場合は複数回に分割し */
/* て処理する */
/*---------------------------------------------------------------------------*/
static void linefeed(int n)
{
while (n>=64)
{
prn_linefeed(64);
n -= 64;
}
prn_linefeed(n);
}
/*****************************************************************************/
/* 文字列処理・ファイル入力 */
/*****************************************************************************/
/*----------------------------ファイル入力-----------------------------------*/
static int Ungetc_num = 0;
static ushort Ungetc_buf[LINE_MAXCHARNUM+1]; /* xungetc()用のバッファ */
static FILE *Fp;
ushort xgetc(void)
{
ushort c;
if (Ungetc_num)
return Ungetc_buf[--Ungetc_num];
c = getc(Fp);
if (iskanji(c))
return (c<<8) + getc(Fp);
else
return c;
}
void xungetc(ushort c)
{
Ungetc_buf[Ungetc_num++] = c;
}
/*----------------------行末禁則文字かどうかの判定---------------------------*/
static int islastillegal(ushort c)
{
char buf[3];
if (BYTEWIDTH(c)==2)
{
buf[0] = c>>8;
buf[1] = c;
buf[2] = '\0';
}
else
{
buf[0] = c;
buf[1] = '\0';
}
return jstrstr(Lastillegal_tbl,buf)!=NULL;
}
/*----------------------行頭禁則文字かどうかの判定---------------------------*/
static int isfirstillegal(ushort c)
{
char buf[3];
if (BYTEWIDTH(c)==2)
{
buf[0] = c>>8;
buf[1] = c;
buf[2] = '\0';
}
else
{
buf[0] = c;
buf[1] = '\0';
}
return jstrstr(Firstillegal_tbl,buf)!=NULL;
}
/*****************************************************************************/
/* プリンタ出力 */
/*****************************************************************************/
/*----------------------パラメータを表示して確認をとる-----------------------*/
/* 一部に、一度ドット数に換算してからさらにもう一度mmに直しているために二重の*/
/* 誤差が発生している部分がある */
/*---------------------------------------------------------------------------*/
static void showoption(void)
{
fputs("機種設定 : ",stderr);
if (Options.tostdout) fputs("標準出力へ出力\n",stderr);
else
{
switch (Prn_machine)
{
case PRNBIOS_NEC98: fputs("PC-9800" ,stderr); break;
case PRNBIOS_TOWNS: fputs("FMR/TOWNS",stderr); break;
case PRNBIOS_IBMPC: fputs("DOS/V" ,stderr); break;
case PRNBIOS_J3100: fputs("J-3100/AX",stderr); break;
}
fprintf(stderr," + ");
switch (Prn_mode)
{
case PRNMODE_ESCP: fputs("ESC/P-J84",stderr); break;
case PRNMODE_MSX: fputs("MSX" ,stderr); break;
case PRNMODE_PCPR: fputs("PC-PR201H",stderr); break;
case PRNMODE_FMPR: fputs("FMPR" ,stderr); break;
}
putc('\n',stderr);
}
fprintf(stderr,"\n印刷するファイル : %s\n",Pathname);
fprintf(stderr, "物理マージン : 上%dmm 左%dmm\n"
"\n"
"用紙サイズ : 横%dmm×縦%dmm\n"
"論理マージン : 上%dmm 左%dmm 右%dmm 下%dmm\n"
"印字方向 : %s書き\n"
"出力する範囲 : %d~%dページ(ページ番号 %+d)\n"
"1字の幅 : 全角あたり 横%d×縦%dドット\n"
"字詰め : %d字×%d行\n"
"段組 : %d段(段幅%dmm",
Options.pmargin .u, Options.pmargin .l,
Options.papersize.x, Options.papersize.y,
Options.lmargin .u, Options.lmargin .l,
Options.lmargin .r, Options.lmargin .d,
(Options.istategaki ? "縦" : "横" ),
Options.area.s,Options.area.e,Options.area.n,
Format.blocksize.x*2/Options.charnum.x,
Format.blocksize.y /Options.charnum.y,
Options.charnum.x, Options.charnum.y,
Options.block.num, (int)DOT2MM(Format.blocksize.x));
if (Options.block.num>=2)
fprintf(stderr," 段間%dmm",Options.block.space);
fputs(")\n\nヘッダ : ",stderr);
if (Options.header==NULL)
fputs("(なし)",stderr);
else
fprintf(stderr,"%s",Options.header);
fputs("\nフッタ : ",stderr);
if (Options.footer==NULL)
fputs("(なし)",stderr);
else
fprintf(stderr,"%s",Options.footer);
fputs("\n\nこれでよろしいですか(y/n)",stderr);
while (1)
{
switch (getch())
{
case 'Y':
case 'y':
case '\r':
case '\n':
fputs("Y\n",stderr);
return;
case 'N':
case 'n':
case '\3':
fputs("N\n",stderr);
exit(1);
default:
putc('\a',stderr);
}
}
}
/*--------------------------------初期化-------------------------------------*/
static void init(char *filename)
{
Pathname = filename; /* strdupは不要 */
Filename = jstrrchr(Pathname,'\\');
if (Filename==NULL)
{
if (Pathname[1]==':')
Filename = Pathname+2;
else
Filename = Pathname;
}
else
Filename++;
Fp = fopen(filename,"r");
if (Fp==NULL)
{
fprintf(stderr,"ファイル %s がオープンできません\n",filename);
exit(1);
}
Pagenum = 1;
Linebuf = (struct LINEBUF *)malloc
(sizeof(struct LINEBUF)*Options.charnum.y*Options.block.num);
if (Linebuf==NULL)
{
fprintf(stderr,"メモリ不足です\n");
exit(1);
}
if (Options.tostdout)
{
Format.xwidth = Options.charnum.x*Options.block.num
+ Options.block.space*(Options.block.num-1);
return;
}
else /* !Options.tostdout */
{
if (Options.pmargin.u>Options.lmargin.u ||
Options.pmargin.l>Options.lmargin.l)
{
fprintf(stderr,"論理マージンが物理マージンより小さくなっています.\n");
exit(1);
}
Format.blocksize.x = MM2DOTS(Options.papersize.x
- Options.lmargin.l - Options.lmargin.r
- (Options.block.num-1)*Options.block.space)
/ Options.block.num;
Format.blocksize.y = MM2DOTS(Options.papersize.y
- Options.lmargin.u - Options.lmargin.d );
if (Format.blocksize.x<=0 || Format.blocksize.y<=0)
{
fprintf(stderr,"マージンが多すぎて印刷可能範囲がありません.\n");
exit(1);
}
Format.xwidth = MM2DOTS(Options.papersize.x
- Options.lmargin.l - Options.lmargin.r);
Format.blockspace=MM2DOTS(Options.block.space);
Format.margin.u =MM2DOTS(Options.lmargin.u-Options.pmargin.u);
Format.margin.l =MM2DOTS(Options.lmargin.l-Options.pmargin.l);
if (Options.header!=NULL)
Format.blocksize.y -= HEADER_YSPACE+24;
if (Options.footer!=NULL)
Format.blocksize.y -= FOOTER_YSPACE+24;
showoption();
}
}
/*--------------------------ヘッダの特殊コードの処理-------------------------*/
/* 返した内容は次に呼び出すまで有効。返した領域を自由に書き換えてもよい */
/*---------------------------------------------------------------------------*/
static char *compile_header(char *header)
{
static char buf[256];
char *p = buf;
char c;
while ((c=*header++)!='\0')
{
if (c!='%')
{
*p++ = c;
if (iskanji(c))
*p++ = *header++;
continue;
}
switch (c=toupper(*header++))
{
case 'P': p += sprintf(p,"%s",Pathname); break;
case 'F': p += sprintf(p,"%s",Filename); break;
case 'N': p += sprintf(p,"%d",Pagenum+Options.area.n); break;
default : *p++ = c;
}
}
*p = '\0';
return buf;
}
/*-----------------------ページの出力(標準出力へ)----------------------------*/
static void putpage_to_stdout(void)
{
int i,j,k; /* ループカウンタ */
int line; /* putpage()のコメント参照 */
line = CEIL(Linenum,Options.block.num);
if (Options.header!=NULL)
{
char *p = compile_header(Options.header);
printf("%*s%s\n\n",(Format.xwidth-strlen(p))/2,"",p);
}
for (i=0 ; i<line ; i++)
{
for (j=0 ; ; )
{
int n=0;
struct LINEBUF buf;
if (j*line+i>=Linenum)
{
printf("%*s",Options.charnum.x,"");
goto next;
}
buf = Linebuf[j*line+i];
for (k=0 ; k<buf.charnum ; k++)
{
n += BYTEWIDTH(buf.buf[k]);
if (BYTEWIDTH(buf.buf[k])==2)
putchar(buf.buf[k]>>8);
putchar((unsigned char)buf.buf[k]);
}
free(buf.buf);
next:
if (++j==Options.block.num)
break;
printf("%*s",Options.charnum.x-n+Options.block.space,"");
}
putchar('\n');
}
for (i=line ; i<Options.charnum.y ; i++)
putchar('\n');
if (Options.footer!=NULL)
{
char *p = compile_header(Options.footer);
printf("\n%*s%s\n",(Format.xwidth-strlen(p))/2,"",p);
}
for (i=0 ; i<Options.lmargin.d ; i++)
putchar('\n');
Pagenum++;
Linenum = 0;
}
/*-----------------------ページの出力(プリンタへ)----------------------------*/
static void putpage(void)
{
int i,j,k; /* ループカウンタ */
int line; /* 印刷する物理行数;ceil(バッファの行数/段数)*/
int feeded = 0; /* これまでに出力された改行の量 */
if (Pagenum<Options.area.s || Pagenum>Options.area.e)
{
for (i=0 ; i<Linenum ; i++)
free(Linebuf[i].buf);
goto end_of_output;
}
if (Options.tostdout)
{
putpage_to_stdout();
return;
}
while (kbhit())
;
fprintf(stderr,"%dページを印刷します 何かキーを押してください",Pagenum); if (getch()=='\3')
{
fputs("^C\n",stderr);
exit(0);
}
if (Pagenum==1 || Pagenum==Options.area.s)
prn_init();
if (Options.istategaki)
prn_tategaki(PRNTATE_NOHALF);
fprintf(stderr,"\n%dページを印刷中です\n",Pagenum);
linefeed(Format.margin.u);
if (Options.header!=NULL)
{
char *s = compile_header(Options.header);
prn_setcarridge(Format.margin.l +
(Format.xwidth - strlen(s)*PRN_CHRWIDTH/2)/2);
prn_putstr(s);
linefeed(HEADER_YSPACE+24);
}
line = CEIL(Linenum,Options.block.num);
for (i=0 ; i<line ; i++)
{
int pos;
for (j=0,pos=Format.margin.l ; j<Options.block.num ;
j++ , pos += Format.blocksize.x+Format.blockspace)
{
struct LINEBUF buf;
int n; /* 出力されたバイト数 */
if (j*line+i>=Linenum)
continue;
buf = Linebuf[j*line+i];
n = 0;
for (k=0 ; k<buf.charnum ; k++)
{
prn_setcarridge(pos + (long)n*
Format.blocksize.x/buf.bytenum);
prn_putchar(buf.buf[k]);
n += BYTEWIDTH(buf.buf[k]);
}
free(buf.buf);
}
/* 丸め誤差が出ないように面倒な計算をする */
/* longで計算するのはオーバーフロー防止のため */
j = (i+1L)*(long)Format.blocksize.y/Options.charnum.y;
linefeed(j-feeded);
feeded = j;
}
linefeed(Format.blocksize.y - feeded);
if (Options.footer!=NULL)
{
char *s = compile_header(Options.footer);
linefeed(FOOTER_YSPACE);
prn_setcarridge(Format.margin.l +
(Format.xwidth - strlen(s)*PRN_CHRWIDTH/2)/2);
prn_putstr(s);
linefeed(24);
}
prn_tategaki(PRNTATE_NONE);
prn_formfeed();
end_of_output:
Pagenum++;
Linenum = 0;
}
/*----------------------最終ページの出力 & 後始末----------------------------*/
static void lastpage(void)
{
if (Linenum)
putpage();
free(Linebuf);
fclose(Fp);
}
/*------------------------行単位でバッファに格納-----------------------------*/
static void putout(ushort *buf,int charnum,int bytenum,int islf)
{
static int nocheck = 0; /* その行だけ禁則処理を行わないフラグ */
ushort c,nextchar;
if (islf)
{
bytenum = Options.charnum.x;
goto output_main;
}
nextchar = xgetc();
if (nextchar=='\n' || nextchar==EOF)
goto output_main;
if (nocheck)
{
nocheck = 0;
xungetc(nextchar);
goto output_main;
}
while (bytenum>=Options.charnum.x/2) /* while(bytenum)とすべきか? */
{
c = buf[charnum-1];
if (islastillegal(c) || isfirstillegal(nextchar))
{
charnum--;
xungetc(nextchar);
nextchar = c;
bytenum -= BYTEWIDTH(c);
}
else
{
xungetc(nextchar);
goto output_main;
}
}
/* 禁則処理で長さが半分未満になった場合 */
xungetc(nextchar);
while (charnum)
xungetc(buf[--charnum]);
nocheck = 1;
return;
output_main:
if (charnum)
{
Linebuf[Linenum].buf = (ushort*)malloc(charnum*sizeof(ushort));
if (Linebuf[Linenum].buf==NULL)
{
fprintf(stderr,"メモリ不足です\n");
exit(1);
}
memcpy(Linebuf[Linenum].buf,buf,charnum*sizeof(ushort));
}
Linebuf[Linenum].charnum = charnum;
Linebuf[Linenum].bytenum = bytenum;
if (++Linenum==Options.block.num*Options.charnum.y)
putpage();
}
/*---------------------プリンタ出力のメインルーチン--------------------------*/
static void xmain(char *filename)
{
int charnum = 0; /* 現在入力中の文字列の文字数 */
int bytenum = 0; /* 現在入力中の文字列のバイト数 */
ushort buf[LINE_MAXCHARNUM];
ushort c;
init(filename);
while ((c=xgetc())!=EOF)
{
if (c=='\n')
{
putout(buf,charnum,bytenum,1);
charnum = bytenum = 0;
continue;
}
else if (c=='\t')
{
int n = bytenum + Options.tabstop -
bytenum%Options.tabstop;
if (n>Options.charnum.x)
n = Options.charnum.x;
for ( ; bytenum<n ; bytenum++)
buf[charnum++] = ' ';
if (n==Options.charnum.x)
{
putout(buf,charnum,bytenum,1);
charnum=bytenum=0;
continue;
}
}
else if (BYTEWIDTH(c)==1 && iscntrl(c))
continue;
else
{
buf[charnum++] = c;
bytenum += BYTEWIDTH(c);
}
if (bytenum>=Options.charnum.x)
{
if (bytenum>Options.charnum.x)
{
xungetc(buf[--charnum]);
bytenum -= 2; /* はみ出すのは全角のみ */
}
putout(buf,charnum,bytenum,0);
charnum = bytenum = 0;
}
}
if (charnum)
putout(buf,charnum,bytenum,1);
lastpage();
}
/*****************************************************************************/
/* オプションの解析 */
/*****************************************************************************/
/*--------------------------S(用紙サイズ)オプション--------------------------*/
static int option_s(char *s)
{
int a,b;
if (isdigit(s[0]))
{
return sscanf(s,"%u,%u",&Options.papersize.x,
&Options.papersize.y)==2;
}
a = toupper(s[0])-'A';
if (a!=0 && a!=1)
return 0;
b = s[1]-'0';
if (b<0 || 6
<b)
return 0;
if (s[2]=='R' || s[2]=='r' || s[2]=='\0')
{
Options.papersize.x = Papersize[a][b+1];
Options.papersize.y = Papersize[a][b ];
}
else if (s[2]=='L' || s[2]=='l')
{
Options.papersize.x = Papersize[a][b ];
Options.papersize.y = Papersize[a][b+1];
}
else
return 0;
return 1;
}
/*----------------------C(コンピュータの機種)オプション----------------------*/
static int option_c(char *s)
{
if (*s=='N' || *s=='n' || *s=='9') Prn_machine=PRNBIOS_NEC98;
else if (*s=='F' || *s=='f') Prn_machine=PRNBIOS_TOWNS;
else if (*s=='I' || *s=='i') Prn_machine=PRNBIOS_IBMPC;
else if (*s=='J' || *s=='j' || *s=='A' || *s=='a')
Prn_machine=PRNBIOS_J3100;
else
return 0;
return 1;
}
/*-------------------------P(プリンタの機種)オプション-----------------------*/
static int option_p(char *s)
{
if (*s=='!')
{
Options.tostdout = 1;
Options.lmargin.d = 1;
return 1;
}
Options.tostdout = 0;
if (*s=='E' || *s=='e') Prn_mode=PRNMODE_ESCP;
else if (*s=='M' || *s=='m') Prn_mode=PRNMODE_MSX;
else if (*s=='P' || *s=='p') Prn_mode=PRNMODE_PCPR;
else if (*s=='F' || *s=='f') Prn_mode=PRNMODE_FMPR;
else
return 0;
return 1;
}
/*----------------------------?(ヘルプ)オプション----------------------------*/
/* このオプションの出力は通常のstderrではなくstdoutにする(リダイレクトできる */
/* ように) */
/*---------------------------------------------------------------------------*/
static void option_help(void)
{
printf( "書式 : ATHENA [オプション] ファイル名\n"
"\n"
"オプション:\n"
" -C{NEC|FM|IBM|J31|AX} コンピュータの機種\n"
" -P{ESCP|MSX|PCPR|FMPR} プリンタの機種\n"
" -S横幅,縦幅/-S{A|B}{3|4|5|6}[L] 用紙サイズ\n"
" -L上,左 -M上,左,右,下 物理マージン,論理マージン\n"
" -K段数,段間スペース 段組の指定\n"
" -N横,縦 段の字数\n"
" -T数値 タブ幅\n"
" -W[{0|1}] 縦書きの指定\n"
" -H\"ヘッダ\",-F\"フッタ\" ヘッダ,フッタ\n"
" -A開始頁,終了頁[,頁番号オフセット] 印刷する範囲の指定\n"
"\n"
" @ファイル名 パラメータをファイルで指定\n"
"\n"
"オプションでの長さの指定はmm単位です\n");
exit(0);
}
/*-----------------------オプション解析のメインルーチン----------------------*/
static void option(char *s)
{
switch (toupper(s[1]))
{
case 'C':
if (!option_c(s+2))
goto error;
break;
case 'P':
if (!option_p(s+2))
goto error;
break;
case 'S':
if (!option_s(s+2))
goto error;
break;
case 'L':
sscanf(s+2,"%d,%d",&Options.pmargin.u,&Options.pmargin.l);
break;
case 'M':
sscanf(s+2,"%u,%u,%u,%u",&Options.lmargin.u,
&Options.lmargin.l,&Options.lmargin.r,&Options.lmargin.d);
break;
case 'H':
if (Options.header!=NULL)
free(Options.header);
if (s[2]=='\0')
Options.header = NULL;
else if ((Options.header=strdup(s+2))==NULL)
goto nomem;
break;
case 'F':
if (Options.footer!=NULL)
free(Options.footer);
if (s[2]=='\0')
Options.footer = NULL;
else if ((Options.footer=strdup(s+2))==NULL)
goto nomem;
break;
case 'K':
sscanf(s+2,"%u,%u",&Options.block.num,&Options.block.space);
break;
case 'N':
sscanf(s+2,"%u,%u",&Options.charnum.x,&Options.charnum.y);
break;
case 'A':
sscanf(s+2,"%u,%u,%d",&Options.area.s,&Options.area.e,
&Options.area.n);
if (Options.area.s>Options.area.e)
goto error;
break;
case 'T':
sscanf(s+2,"%u",&Options.tabstop);
break;
case 'W':
if (s[2]=='1' || s[2]=='\0') /* 単に-Wは-W1とみなす */
Options.istategaki = 1;
else
Options.istategaki = 0;
break;
case '?': option_help(); /* 返ってこないからbreakは要らない */
default: goto error;
}
return;
error:
fprintf(stderr, "不正なオプションです:%s\n\n"
"ヘルプを見るには ATHENA -?としてください.\n",s);
exit(1);
nomem:
fprintf(stderr,"メモリ不足です\n");
exit(1);
}
/*****************************************************************************/
/* スタートアップ */
/*****************************************************************************/
/*------------------------オプションの読みとりに使う変数---------------------*/
static FILE *Responsefile = NULL; /* レスポンスファイル */
static char *Argbuf; /* 現在読み込んであるバッファの内容 */
static char **Argv; /* コマンドラインのパラメータ */
/*--------------------行バッファからのトークンの切り出し---------------------*/
/* gettoken()が返した値は、次に呼び出すまで有効。自由に書き換えてよい */
/*---------------------------------------------------------------------------*/
#define gettoken_init(s) (Argbuf=(s))
static char *gettoken(void)
{
int isinsidequote = 0;
char *ret;
while (isspace(*Argbuf))
Argbuf++;
if (*Argbuf=='\0')
return NULL;
for (ret=Argbuf ; ; Argbuf++)
{
char c = *Argbuf;
if (c=='\0')
{
if (isinsidequote)
{
/* このエラーメッセージはLSI Cの */
/* 標準のものに合わせた。 */
fprintf(stderr,"Unmatched quote.\n");
exit(1);
}
else
break;
}
if (c=='"')
isinsidequote = !isinsidequote;
if (!isinsidequote && isspace(c))
{
*Argbuf = '\0';
break;
}
if (iskanji(c) || (isinsidequote && c=='^') )
Argbuf++;
}
return ret;
}
/*------------------コマンドラインパラメータ入力の初期化---------------------*/
static void init_arg(char **argv)
{
Argv = argv+1;
gettoken_init(strdup(getenv("ATHENA")));
}
/*--------------------------パラメータの獲得---------------------------------*/
/* この関数が返したバッファは、次にこの関数を呼び出すまで有効。 */
/*---------------------------------------------------------------------------*/
static char *getarg(void)
{
char *s;
static char *buf;
rep1:
s = gettoken();
if (s!=NULL)
return s;
rep2:
if (Responsefile==NULL)
{
if (Argv[0]==NULL || Argv[0][0]!='@')
return *Argv++;
Responsefile = fopen(Argv[0]+1,"r");
if (Responsefile==NULL)
{
fprintf(stderr,"ファイル%sがオープンできません\n",
Argv[0]+1);
exit(1);
}
}
if (fgets(buf,sizeof(buf),Responsefile)!=NULL)
{
gettoken_init(buf);
goto rep1;
}
else
{
fclose(Responsefile);
Responsefile = NULL;
goto rep2;
}
}
/*---------------------------メインルーチン----------------------------------*/
extern int main(int argc,char **argv)
{
char *s;
fputs("テキスト印刷 8086|Printman/TEXT 'Athena' Version 1.00a\n\n",stderr);
init_arg(argv);
while ((s=getarg())!=NULL)
{
if (*s=='-')
option(s);
else
xmain(s);
}
return 0;
}
/*-------------------------------コラム--------------------------------------*/
/* このプログラムは次のようなことを仮定している。 */
/* (1)半角の文字コードはASCIIあるいはそれを拡張した形式 */
/* (2)全角の文字コードはシフトJISやEUCのように、ASCIIと共存できる形式 */
/* (ただし、シフトJIS以外のときはiskanji()の差し替えが必要) */
/* (3)定数EOFはwchar_tのどの有効な文字とも異なる */
/* (4)charは8ビット */
/* (5)unsignedとsignedの内部表現は同じ */
/* (計算の都合上(例えば1U<-1は1U<UINT_MAXとみなされ真となる)変数を */
/* signedで宣言しておきながら、sscanf()では"%u"を使用している) */
/*--------------------------End of Athena.c----------------------------------*/